﻿
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Transactions;
using Tauren.File.DLL.FileDLL;
using Tauren.File.DLL.FileIODLL;
using Tauren.File.DLL.FolderDLL;
using Tauren.File.DLL.Resouces;
using Tauren.File.Entity.Config;
using Tauren.File.Entity.Const;
using Tauren.File.Entity.Enum;
using Tauren.File.Entity.Global;
using Tauren.File.Entity.Input;
using Tauren.File.Entity.Model;
using Tauren.File.Entity.Output;
using Tauren.File.Infrastructure.Common;
using Tauren.File.Infrastructure.Globals;

namespace Tauren.File.Service.FileBLL
{
    /// <summary>
    /// 文件信息
    /// </summary>
    public class FileService : Base.BaseService, IFileService
    {
        private IFileBusiness business;
        private IFileIOBusiness IOBusiness;
        private IFileFolderBusiness folderBusiness;
        private FilePath filePath;
        public FileService(IFileBusiness baseDLL, IConnectionBLLBase connectionBLL, IConfiguration configuration, IMenuResourcesBusiness resourcesBusiness, IFileFolderBusiness _folderBusiness, IFileIOBusiness _IOBusiness) : base(baseDLL, connectionBLL, resourcesBusiness)
        {
            business = baseDLL;
            this.ResourcesInfo = this.GetResources(GlobalConst.RESOURCES_FLAG_MODULE_FILEFOLDER_KEY);
            this.JudePrmission(GlobalConst.RESOURCES_FLAG_MODULE_FILEFOLDER_KEY.ToLower());
            ///获取配置文件中的数据 
            filePath = configuration.Get<ApiVersionsConfig>().FilePath;
            IOBusiness = _IOBusiness;
            folderBusiness = _folderBusiness;
        }

        public IResponseMessage Add(Files_Input model)
        {
            if (!HavePermission) return ErrorType.BUSINESS_WITHOUT_PERMISSION.Failure(this.CommonText(ErrorType.BUSINESS_WITHOUT_PERMISSION));
            if (model is null) return GlobalErrorType.GLOBAL_NOT_FOUND_INPUT_DATA.Failure(this.CommonText(GlobalErrorType.GLOBAL_NOT_FOUND_INPUT_DATA));
            Files files;
            ToModel(model, out files);
            FileFolder fileFolder = business.Get<FileFolder>(files.FolderId);
            if (fileFolder is null) return GlobalErrorType.GLOBAL_SAVE_FAILURE.OnSucceed(this.CommonText(GlobalErrorType.GLOBAL_NOT_FOUND_DB_DATA));
            files.Path = fileFolder.Path;
            using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = IsolationLevel.ReadCommitted }))
            {
                CreateFile(files);
                files.Enable = true;
                files.Sequence = business.GetSeq();
                files.Creator = Global.EmpId;
                files.Modifier = Global.EmpId;
                files.Creatdate = DateTime.Now;
                files.Modifdate = DateTime.Now;
                if (business.Add(files) > 0)
                {
                    ts.Complete();
                    return "".OnSucceed(this.CommonText(GlobalErrorType.GLOBAL_SAVE_SUCCESSINFO.ToString()));
                }
                else return GlobalErrorType.GLOBAL_SAVE_FAILURE.OnSucceed(this.CommonText(GlobalErrorType.GLOBAL_SAVE_FAILURE));
            }
        }

        public IResponseMessage Config(string PageType)
        {
            if (!HavePermission) return ErrorType.BUSINESS_WITHOUT_PERMISSION.Failure(this.CommonText(ErrorType.BUSINESS_WITHOUT_PERMISSION));
            List<OutPutConfig> Fields = new List<OutPutConfig>();

            OutPutConfig config = new OutPutConfig();
            Dictionary<object, object> rule = new Dictionary<object, object>();

            #region 中文名
            config = new OutPutConfig();
            config.Label = this.CommonText("thcnname");
            config.FieldKey = "cnName";
            config.MenuCode = GlobalConst.RESOURCES_FLAG_MODULE_FILEFOLDER_KEY.ToLower();
            config.ControlType = ControlType.textarea;
            config.Show = true;
            config.Editor = PageType != "view";
            config.Required = PageType != "view";
            rule = new Dictionary<object, object>();
            if (PageType != "view")
            {
                rule.Add("required", true);
                rule.Add("message", this.CommonText("fieldsrequired"));
                rule.Add("trigger", "blur");
                config.Rules.Add(rule);
                ///长度
                rule = new Dictionary<object, object>();
                rule.Add("min", 1);
                rule.Add("max", 100);
                rule.Add("message", this.Resources("fieldnamemax"));
                rule.Add("trigger", "blur");
                config.Rules.Add(rule);
            }
            Fields.Add(config);
            #endregion

            #region 英文名
            config = new OutPutConfig();
            config.Label = this.CommonText("thenname");
            config.FieldKey = "enName";
            config.MenuCode = GlobalConst.RESOURCES_FLAG_MODULE_FILEFOLDER_KEY.ToLower();
            config.ControlType = ControlType.textarea;
            config.Show = true;
            config.Editor = PageType != "view";
            config.Required = PageType != "view";
            rule = new Dictionary<object, object>();
            if (PageType != "view")
            {
                rule.Add("required", true);
                rule.Add("message", this.CommonText("fieldsrequired"));
                rule.Add("trigger", "blur");
                config.Rules.Add(rule);
                ///长度
                rule = new Dictionary<object, object>();
                rule.Add("min", 1);
                rule.Add("max", 200);
                rule.Add("message", this.Resources("fieldennamemax"));
                rule.Add("trigger", "blur");
                config.Rules.Add(rule);
            }
            Fields.Add(config);
            #endregion
            return Fields.Succeed();
        }

        public IResponseMessage Delete(long id)
        {
            if (!HavePermission) return ErrorType.BUSINESS_WITHOUT_PERMISSION.Failure(this.CommonText(ErrorType.BUSINESS_WITHOUT_PERMISSION));
            Files dbModble = business.Get<Files>(id);
            if (dbModble is null) return GlobalErrorType.GLOBAL_NOT_FOUND_DB_DATA.Failure(this.CommonText(GlobalErrorType.GLOBAL_NOT_FOUND_DB_DATA));
            dbModble.Enable = false;
            dbModble.Modifier = Global.EmpId;
            dbModble.HaveDelete = true;
            dbModble.Modifdate = DateTime.Now;
            if (business.Update(dbModble))
                return "".OnSucceed(this.Resources(GlobalErrorType.GLOBAL_DELETE_SUCCESSINFO));
            else return GlobalErrorType.GLOBAL_DELETE_FAILURE.OnSucceed(this.CommonText(GlobalErrorType.GLOBAL_DELETE_FAILURE));
        }

        public IResponseMessage Edit(Files_Input model)
        {
            if (!HavePermission) return ErrorType.BUSINESS_WITHOUT_PERMISSION.Failure(this.CommonText(ResourcesKey: ErrorType.BUSINESS_WITHOUT_PERMISSION));
            if (model is null) return GlobalErrorType.GLOBAL_NOT_FOUND_INPUT_DATA.Failure(this.CommonText(ResourcesKey: GlobalErrorType.GLOBAL_NOT_FOUND_INPUT_DATA));
            Files dbModble = business.Get<Files>(id: model.AutoId);
            if (dbModble is null) return GlobalErrorType.GLOBAL_NOT_FOUND_DB_DATA.Failure(this.CommonText(ResourcesKey: GlobalErrorType.GLOBAL_NOT_FOUND_DB_DATA));
            dbModble.CNName = model.CNName;
            dbModble.ENName = model.ENName;
            dbModble.Modifier = Global.EmpId;
            dbModble.Modifdate = DateTime.Now;
            if (business.Update(model: dbModble))
                return "".OnSucceed(this.CommonText(ResourcesKey: GlobalErrorType.GLOBAL_SAVE_SUCCESSINFO.ToString()));
            else return GlobalErrorType.GLOBAL_SAVE_FAILURE.OnSucceed(this.CommonText(ResourcesKey: GlobalErrorType.GLOBAL_SAVE_FAILURE));
        }

        public IResponseMessage Enable(long AutoID)
        {
            if (!HavePermission) return ErrorType.BUSINESS_WITHOUT_PERMISSION.Failure(this.CommonText(ErrorType.BUSINESS_WITHOUT_PERMISSION));
            Files dbModble = business.Get<Files>(AutoID);
            if (dbModble is null) return GlobalErrorType.GLOBAL_NOT_FOUND_DB_DATA.Failure(this.CommonText(GlobalErrorType.GLOBAL_NOT_FOUND_DB_DATA));
            dbModble.Enable = !dbModble.Enable;
            dbModble.Modifier = Global.EmpId;
            dbModble.Modifdate = DateTime.Now;
            if (business.Update(dbModble))
                return "".OnSucceed(this.CommonText(dbModble.Enable ? GlobalErrorType.GLOBAL_ENABLE_SUCCESSINFO : GlobalErrorType.GLOBAL_DISABLE_SUCCESSINFO));
            else return dbModble.Enable ? GlobalErrorType.GLOBAL_ENABLE_FAILURE.OnSucceed(this.CommonText(GlobalErrorType.GLOBAL_ENABLE_FAILURE)) : GlobalErrorType.GLOBAL_DISABLE_FAILURE.OnSucceed(this.CommonText(GlobalErrorType.GLOBAL_DISABLE_FAILURE));
        }

        public IResponseMessage Get(object id)
        {
            Files files = business.Get<Files>(id);
            Files_OutPut _OutPut = new Files_OutPut();
            ToViewModel(files, out _OutPut);
            if (_OutPut is null) return new FileFolder_OutPut().Succeed();
            return _OutPut.Succeed();
        }
        /// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="file"></param>
        /// <param name="folderId"></param>
        /// <returns></returns>
        public IResponseMessage Upload(IFormFile file, long folderId)
        {
            if (!HavePermission) return ErrorType.BUSINESS_WITHOUT_PERMISSION.Failure(this.CommonText(ErrorType.BUSINESS_WITHOUT_PERMISSION));
            if (file.Length <= 0) return ErrorType.BUSSINESS_UPLOAD_FILE_SIZE_EMPTY.Failure(this.CommonText(ErrorType.BUSSINESS_UPLOAD_FILE_SIZE_EMPTY));
            if (file.Length > filePath.FileMaxSize) return ErrorType.BUSSINESS_UPLOAD_FILE_SIZE.Failure(this.CommonText(ErrorType.BUSSINESS_UPLOAD_FILE_SIZE));
            var suffix = Path.GetExtension(file.FileName);
            if (!filePath.LimitTypes.Any(p => p == suffix)) return ErrorType.BUSSINESS_UPLOAD_FILE_SUFFIX.Failure(this.CommonText(ErrorType.BUSSINESS_UPLOAD_FILE_SUFFIX));
            Files files = new Files() { CNName = file.FileName.Replace(suffix, ""), ENName = file.FileName.Replace(suffix, ""), Size = file.Length, Ext = suffix.Trim('.'), FolderId = folderId };
            CreateUploadFile(files);
            using (FileStream fs = System.IO.File.Create(files.FilePath))//注意路径里面最好不要有中文
            {
                file.CopyTo(fs);//将上传的文件文件流，复制到fs中
                fs.Flush();//清空文件流
            }
            files.Enable = true;
            files.Sequence = business.GetSeq();
            files.Creator = Global.EmpId;
            files.Modifier = Global.EmpId;
            files.Creatdate = DateTime.Now;
            files.Modifdate = DateTime.Now;
            long Id = business.Add(files);
            if (Id > 0)
            {
                return Id.OnSucceed(this.CommonText(GlobalErrorType.GLOBAL_SAVE_SUCCESSINFO.ToString()));
            }
            else return GlobalErrorType.GLOBAL_SAVE_FAILURE.OnSucceed(this.CommonText(GlobalErrorType.GLOBAL_SAVE_FAILURE));
        }
        public IResponseMessage GetFiles(string[] ids)
        {
            if (!ids.Any()) return new List<PageDocumentCenterTable>().Succeed();
            var files = business.GetFiles(ids).Select(o => new PageDocumentCenterTable()
            {
                AutoId = o.AutoId,
                CNName = o.FileType != "0" ? $"{o.CNName}.{o.Ext}" : o.CNName,
                ENName = o.FileType != "0" ? $"{o.ENName}.{o.Ext}" : o.ENName,
                Ext = o.Ext,
                Dic_FileType = this.CommonText($"file{((TextType)(int.Parse(o.FileType))).ToString()}"),
                Dic_Enable = CommonText(o.Enable ? GlobalConst.RESOURCES_CONTENT_ENABLE_KEY : GlobalConst.RESOURCES_CONTENT_DISABLE_KEY),
                Dic_Creator = EmpDictionary.ContainsKey(o.Creator) ? EmpDictionary[o.Creator] : "",
                Dic_Creatdate = o.Creatdate.Value.ToString(GlobalConst.DATE_FORMAT_SECONDS),
                Row_Style = o.Enable ? "" : "danger",
                Size = o.Size <= 0 ? "" : double.Parse(o.Size + "").CovertToGb(),
                FileUri = string.IsNullOrEmpty(o.FileUri) ? "" : $"{filePath.FileApiUrl}{o.FileUri}",
                FileType = int.Parse(o.FileType)
            });
            return files.Succeed();
        }

        /// <summary>
        /// 删除上传过程中不要的文件
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public IResponseMessage UploadDelete(string[] ids)
        {
            if (!ids.Any()) return new List<PageDocumentCenterTable>().Succeed();
            var files = business.GetFiles(ids);

            for (int i = 0; i < files.Count; i++)
            {
                string physicalFolderPath = $"{ filePath.PhysicalFilePath}{files[i].FolderPath}";
                if (System.IO.File.Exists(files[i].FilePath))
                {
                    System.IO.File.Delete(files[i].FilePath);
                }
                if (System.IO.Directory.Exists(physicalFolderPath))
                {
                    System.IO.Directory.Delete(physicalFolderPath);
                }
            }
            return business.Delete(files).Succeed();
        }
        #region private
        /// <summary>
        /// 创建文件
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        private void CreateFile(Files model)
        {
            ///找到在启用的文件夹
            Physicalhistory physicalhistory = folderBusiness.SingleByEnable();
            ///判断是否最大
            if (IOBusiness.IsFileMaxFolder(model: physicalhistory))
            {
                if (physicalhistory == null)
                {
                    physicalhistory = new Physicalhistory();
                }
                //创建新的文件夹
                SettingPhysicalHistory(physicalhistory: physicalhistory);
                ///将之前的文件夹都禁用
                folderBusiness.Edit();
                ///重新加入文件
                physicalhistory.AutoId = business.Add(model: physicalhistory);///重新加入文件
            }
            IOBusiness.MakeFile(files: model, physicalhistory: physicalhistory);
        }
        /// <summary>
        /// 创建文件
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        private void CreateUploadFile(Files model)
        {
            ///找到在启用的文件夹
            Physicalhistory physicalhistory = folderBusiness.SingleByEnable();
            ///判断是否最大
            if (IOBusiness.IsFileMaxFolder(model: physicalhistory))
            {
                if (physicalhistory == null)
                {
                    physicalhistory = new Physicalhistory();
                }
                //创建新的文件夹
                SettingPhysicalHistory(physicalhistory: physicalhistory);
                ///将之前的文件夹都禁用
                folderBusiness.Edit();
                ///重新加入文件
                physicalhistory.AutoId = business.Add(model: physicalhistory);///重新加入文件
            }
            IOBusiness.MakeUploadFile(files: model, physicalhistory: physicalhistory);
        }

        /// <summary>
        /// 创建新的文件夹
        /// </summary>
        /// <param name="physicalhistory"></param>
        /// <returns></returns>
        private void SettingPhysicalHistory(Physicalhistory physicalhistory)
        {
            physicalhistory.Creator = Global.EmpId;
            physicalhistory.Modifier = Global.EmpId;
            physicalhistory.Creatdate = DateTime.Now;
            physicalhistory.Modifdate = DateTime.Now;
            physicalhistory.AutoId = 0;
            physicalhistory.PhysicalFolder = Guid.NewGuid().ToString().Replace("-", "").Trim();
            physicalhistory.Enable = true;
        }

        /// <summary>
        /// 分页获取文件数据
        /// </summary>
        /// <param name="queryModel"></param>
        /// <returns></returns>
        public IResponseMessage Pages(QueryModel queryModel)
        {
            if (!HavePermission) return ErrorType.BUSINESS_WITHOUT_PERMISSION.Failure(this.CommonText(ErrorType.BUSINESS_WITHOUT_PERMISSION));
            TableListModel<PageDocumentCenterTable> tableListModel = new TableListModel<PageDocumentCenterTable>();
            List<TableListHeaderModele> Headers = new List<TableListHeaderModele>();
            Headers.Add(new TableListHeaderModele() { Key = "rowNo", Name = this.CommonText("rowno"), Width = 50, Fixed = true });
            Headers.Add(new TableListHeaderModele() { Key = "autoId", Name = this.Resources("orgid"), Width = 120, Hide = true, Fixed = true, Type = "primary_key", });
            Headers.Add(new TableListHeaderModele() { Key = "cnName", Name = this.CommonText("thcnname"), Type = "primary_name", Hyperlink = true, IsOperation = true, SorTable = SortType.custom.ToString(), Fixed = true, Width = 360,Filter=true });
            Headers.Add(new TableListHeaderModele() { Key = "enName", Name = this.CommonText("thenname"), Type = "primary_name", Hyperlink = true, SorTable = SortType.custom.ToString(), Fixed = true, Width = 360, Filter = true });
            Headers.Add(new TableListHeaderModele() { Key = "dic_FileType", Name = this.Resources("thfiletype"), Align = "center", IsTag = true, Width = 180 });
            Headers.Add(new TableListHeaderModele() { Key = "ext", Name = this.CommonText("thfileext"), Width = 160, Align = "center", Filter = true });
            Headers.Add(new TableListHeaderModele() { Key = "size", Name = this.CommonText("thfilesize"), Width = 160, Align = "center", Filter = true });
            Headers.Add(new TableListHeaderModele() { Key = "currentVersion", Name = this.CommonText("thfilesizeversion"), Width = 160, Align = "center", Filter = true });
            Headers.Add(new TableListHeaderModele() { Key = "dic_Enable", Name = CommonText("thstate"), IsTag = true, Width = 100, Align = "center", SorTable = SortType.custom.ToString() });
            Headers.Add(new TableListHeaderModele() { Key = "dic_Creator", Name = CommonText("diccreator"), Width = 120, Align = "center" });
            Headers.Add(new TableListHeaderModele() { Key = "dic_Creatdate", Name = CommonText("diccreatdate"), Width = 160, Align = "center" });
            Headers.Add(new TableListHeaderModele() { Key = "action", Name = "操作", Width = 160, Align = "center" });
            long Total = 0;
            List<PageDocumentCenterTable> pageOrganizationTables = business.Pages(queryModel, out Total);
            if (pageOrganizationTables.Any())
            {
                pageOrganizationTables.ForEach(o =>
                {
                    o.Dic_FileType = this.CommonText($"file{((TextType)o.FileType).ToString()}");
                    o.Dic_Enable = CommonText(o.Enable ? GlobalConst.RESOURCES_CONTENT_ENABLE_KEY : GlobalConst.RESOURCES_CONTENT_DISABLE_KEY);
                    o.Dic_Creator = EmpDictionary.ContainsKey(o.Creator) ? EmpDictionary[o.Creator] : "";
                    o.Dic_Creatdate = o.Creatdate.Value.ToString(GlobalConst.DATE_FORMAT_SECONDS);
                    o.Row_Style = o.Enable ? "" : "danger";
                    o.Size = string.IsNullOrEmpty(o.Size) ? "" : double.Parse(o.Size).CovertToGb();
                    o.FileUri = string.IsNullOrEmpty(o.FileUri) ? "" : $"{filePath.FileApiUrl}{o.FileUri}";
                    o.Operations = new List<SystemButton>();
                    if (o.FileType != 0)
                    {
                        o.CNName = $"{o.CNName}.{o.Ext}";
                        o.ENName = $"{o.ENName}.{o.Ext}";
                    }
                    if (Global.IsAdmin && (Buttons is null || !Buttons.Any()))
                    {
                        if (o.FileType == 1 || o.FileType == 2 || o.FileType == 3)
                            BuliderButtons(o.Operations, o.FileType + "", o.AutoId, ButtomType.ondetaildoc);
                        if (o.FileType != 0)
                            BuliderButtons(o.Operations, $"{(Global.IsChinese ? o.CNName : o.ENName)}", o.AutoId, ButtomType.download);
                    }
                    else
                    {
                        if (Buttons.Any(o => o.Location == ButtomLocation.center.ToString() && o.Value == ButtomType.ondetaildoc.ToString()) && (o.FileType == 1 || o.FileType == 2 || o.FileType == 3))
                            BuliderButtons(o.Operations, o.FileType + "", o.AutoId, ButtomType.ondetaildoc);
                        if (Buttons.Any(o => o.Location == ButtomLocation.center.ToString() && o.Value == ButtomType.download.ToString()) && o.FileType != 0)
                            BuliderButtons(o.Operations, $"{(Global.IsChinese ? o.CNName : o.ENName)}", o.AutoId, ButtomType.download);
                    }
                });
            }
            tableListModel.Body = pageOrganizationTables;
            tableListModel.Total = Total;
            tableListModel.Header = Headers;
            return tableListModel.Succeed();
        }

        public IResponseMessage SavePhoto(long fileid, int empid)
        {
            if (fileid < 0) return "".Succeed();
            if (empid == 0) empid = Global.EmpId;
            ExPhotoInfo photo = business.SingePhoto(empid);
            if (photo != null)
            {
                PhotoInfo info = new PhotoInfo();
                info.FileId = fileid;
                info.EmpId = photo.EmpId;
                info.Modifdate = DateTime.Now;
                info.Modifier = Global.EmpId;
                info.Creatdate = photo.Creatdate;
                info.Creator = photo.EmpId;
                info.AutoId = photo.AutoId;
                return business.Update(info).Succeed();
            }
            else
            {
                PhotoInfo info = new PhotoInfo();
                info.FileId = fileid;
                info.EmpId = empid;
                info.Modifdate = DateTime.Now;
                info.Modifier = Global.EmpId;
                info.Creatdate = DateTime.Now;
                info.Creator = Global.EmpId;
                return business.Add(info).Succeed();
            }
        }

        public IResponseMessage GetPhoto(int empid)
        {
            if (empid == 0) empid = Global.EmpId;
            ExPhotoInfo photo = business.SingePhoto(empid);
            if (photo == null) return "".Succeed();
            else return $"{filePath.FileApiUrl}{photo.FileUri}".Succeed();
        }


        #endregion
    }
}
